import { Injectable } from '@angular/core';
import { TREEURL, FILEURL, CDNFILEURL } from '../../config';
import { isNullOrUndefined } from 'util';
import { NzTreeNode, NzTreeNodeOptions } from 'ng-zorro-antd';
import { NeonTreeNode, NeonAngular } from 'src/app/common/neon';
import { NeonService } from '../neon/neon.service';
import { BaseService } from '../base.service';
import { DataManagementService } from '../data-management/data-management.service';
import { ModelService } from './model.service';
import { RequestClientService } from '../request-client.service';
import { ModelDevice } from './model.viewModel';
import { ActivatedRoute } from '@angular/router';
export class FileViewModel {
  public id: string;
  public createdAt: string;
  public createdUserName: string;
  public fileDirectoryId: string;
  public modelGroupId: string;
  public modelPath: string;
  public name: string;
  public path: string;
  public size: number;
  public taskId: string;
  public url: string;
  public constructor(param) {
    (!isNullOrUndefined(param.id)) && (this.id = param.id);
    (!isNullOrUndefined(param.createdAt)) && (this.createdAt = param.createdAt);
    (!isNullOrUndefined(param.createdUserName)) && (this.createdUserName = param.createdUserName);
    (!isNullOrUndefined(param.fileDirectoryId)) && (this.fileDirectoryId = param.fileDirectoryId);
    (!isNullOrUndefined(param.modelGroupId)) && (this.modelGroupId = param.modelGroupId);
    (!isNullOrUndefined(param.modelPath)) && (this.modelPath = param.modelPath);
    (!isNullOrUndefined(param.name)) && (this.name = param.name);
    (!isNullOrUndefined(param.path)) && (this.path = param.path);
    (!isNullOrUndefined(param.size)) && (this.size = param.size);
    (!isNullOrUndefined(param.taskId)) && (this.taskId = param.taskId);
    (!isNullOrUndefined(param.url)) && (this.url = param.url);
  }
}
export class AttachmentViewModel {
  public id: string;
  public createdAt: string;
  public docType: number;
  public fileId: string;
  public fileName: string;
  public filePath: string;
  public version: string;
  public modelGroupId: string;
  public taskId: string;
  public versionRemark: any;
  public orgModelId: any;
  public newModelId: any;
  public open = false;
  public visible = false;
  public treeNode: NzTreeNode;
  public loading = false;
  public percent = 0;
  public children: AttachmentViewModel[] = [];
  public key: any;
  public matrix: gum.Matrix43D;
  public newModel = true;
  public createdUserId: string;
  public constructor(param) {
    let scope = this;
    (!isNullOrUndefined(param.id)) && (this.id = param.id);
    (!isNullOrUndefined(param.createdAt)) && (this.createdAt = param.createdAt);
    (!isNullOrUndefined(param.docType)) && (this.docType = param.docType);
    (!isNullOrUndefined(param.fileId)) && (this.fileId = param.fileId);
    (!isNullOrUndefined(param.fileName)) && (this.fileName = param.fileName);
    (!isNullOrUndefined(param.filePath)) && (this.filePath = param.filePath);
    (!isNullOrUndefined(param.version)) && (this.version = param.version);
    (!isNullOrUndefined(param.modelGroupId)) && (this.modelGroupId = param.modelGroupId);
    (!isNullOrUndefined(param.taskId)) && (this.taskId = param.taskId);
    (!isNullOrUndefined(param.versionRemark)) && (this.versionRemark = param.versionRemark);
    (!isNullOrUndefined(param.orgModelId)) && (this.orgModelId = param.orgModelId);
    (!isNullOrUndefined(param.newModelId)) && (this.newModelId = param.newModelId);
    (!isNullOrUndefined(param.open)) && (this.open = param.open);
    (!isNullOrUndefined(param.visible)) && (this.visible = param.visible);
    (!isNullOrUndefined(param.treeNode)) && (this.treeNode = param.treeNode);
    (!isNullOrUndefined(param.loading)) && (this.loading = param.loading);
    (!isNullOrUndefined(param.percent)) && (this.percent = param.percent);
    (!isNullOrUndefined(param.children)) && (this.children = param.children);
    (!isNullOrUndefined(param.key)) && (this.key = param.key);
    (!isNullOrUndefined(param.newModel)) && (this.newModel = param.newModel);
    (!isNullOrUndefined(param.createdUserId)) && (this.createdUserId = param.createdUserId);
    this.matrix = new gum.Matrix43D();
    if (param.matrix && param.matrix.length > 0) {
      this.matrix.fromArray(param.matrix);
    }
  }



  public applyMatrix() {
    if (this.children && this.children.length > 0) {
      this.children.forEach((avm) => {
        avm.matrix.premultiply(this.matrix);
        avm.applyMatrix();
      });
    }
  }
}


@Injectable()
export class UpdateModelService {
  public modelList: Array<AttachmentViewModel> = [];
  public treeList: NzTreeNode[] = [];
  public showMask = true;
  public leftBench: any;
  public panels: any[];
  public modelGroupId: string;
  public modelTreeList: any = [];
  public showPullMask = false;
  public clickFlag = false;
  public clickMark = false;
  public clickWander = false;

  public leftPanelShow = true;
  public rightPanelShow = false;
  public listType = 0;
  public selectNewModelId: number[] = [];

  public currentPage = 1;
  public deviceDetail: ModelDevice;
  public currentModelLinkId: string;

  public workerTreeType = 1;

  public modelDevicesMap: any = new Map;
  private markButton: any;
  public constructor(
    private requestClientService: RequestClientService,
    private _neonSrv: NeonService,
    private baseSer: BaseService,
    private dataManagementService: DataManagementService
  ) {

    this.panels = [
      {
        active: false,
        disabled: false,
        name: '设计信息',
        label: 'design',
        detail: []
      }
    ];

    this.init();
  }

  public async init() {
    // let projectId = JSON.parse(window.localStorage.getItem('project')).id;
    // console.log(projectId);
    // let res = await this.baseSer.getProById(projectId);
    // if (Date.parse(res.item.createdAt) > Date.parse('2019-01-01T20:00:00')) {
      this.listType = 1;
    // } else {
    //   this.listType = 0;
    // }
  }

  public getHeaderTenantId() {
    return { TenantId: window.localStorage.getItem('TenantId') };
  }

  /**
   * 获取链接关系
   * @param modelGroupId 
   */
  public getModelRelation(modelGroupId: string) {
    return this.requestClientService.get(FILEURL + "/api/v1/BIMModel/modelRelation", { modelGroupId }).then((res) => {
      if (res.success) {
        return res;
      } else {
        return false;
      }
    });
  }

  /**
   * 查询转换进度
   * @param modelGroupId 
   * @param TaskId 转换任务Id
   */
  public getConvertProcess(modelGroupId: string) {
    return this.requestClientService.get(FILEURL + "/api/v1/File/convert-process", { ModelGroupId: modelGroupId }).then((res) => {
      if (res.success) {
        return res;
      } else {
        return false;
      }
    });
  }

  /**
   * 获取所有模型组
   */
  public async getAttachmentGroups(filter) {
    let TenantId = window.localStorage.getItem('projectId');
    let Header = {
      TenantId
    };
    let res = await this.requestClientService.get(TREEURL + '/api/v1/Attachment/Group', filter, Header);
    if (res.success) {
      return res;
    } else {
      return false;
    }
  }

  /**
   * 获取指定Id模型组
   * @param groupId 
   */
  public async getAttachmentByGroupId(groupId: string) {
    let Header = {
      TenantId: localStorage.getItem('projectId')
    };
    let res = await this.requestClientService.get(TREEURL + '/api/v1/Attachment/Group/' + groupId, {}, Header);
    if (res.success) {
      console.log(res);
      return res;
    } else {
      return false;
    }
  }

  /**
   * 删除模型组
   * @param groupId 
   */
  public async deleteGroup(groupId: string) {
    let Header = {
      TenantId: localStorage.getItem('projectId')
    };
    let res = await this.requestClientService.delete(TREEURL + '/api/v1/Attachment/Group', { ModelGroupId: groupId }, Header);
    if (res.success) {
      console.log(res);
      return res;
    } else {
      return false;
    }
  }

  public async gridsAndLevles(modelGroupId: string, modelId: string) {
    let res = await this.baseSer.getGridsAndLevles(modelGroupId, modelId);
    let gridsAndLevels = JSON.parse(res.item);
    console.log(gridsAndLevels);
    // NeonAngular.InitLevelsAndGrids(gridsAndLevels);
  }



  /**
   * 删除指定Id模型
   * @param id 
   */
  public async delOneModel(id) {
    let json = { id };
    let res = await this.requestClientService.delete(`${TREEURL}/api/v1/Attachment`, json, this.getHeaderTenantId());
    return res;
  }

  /**
   * 删除指定文件
   * @param id 
   */
  public async deleteFile(id: string) {
    let res = await this.requestClientService.delete(`${FILEURL}/api/v1/File`, { id }, this.getHeaderTenantId());
    return res;
  }

  /**
   * 上传图片
   * @param formData 
   */
  public async upImg(formData) {
    return this.requestClientService.post(FILEURL + "/api/v1/File", formData, this.getHeaderTenantId()).then((res) => {
      if (res.success) {
        return res;
      } else {
        return false;
      }
    });
  }

  /**
   * 获取模型目录树请求
   * @param modelGroupId 
   * @param modelId 模型在组内的id
   */
  public async getModelTreeSev(modelGroupId: string, modelId: number) {
    let res = await this.requestClientService.get(FILEURL + '/api/v1/BIMModel/modelTree',
      { modelGroupId, modelId }
    );
    console.log(res);
    if (res.success) {
      return res;
    }
  }

  /**
   * 创建bench
   */
  public async createBench() {
    // 启动插件
    // new PrintPlugin();
    // this.markButton = new MarkPlugin();
    // 渲染文件
    const left: HTMLDivElement = document.getElementById('ModelContainer') as HTMLDivElement;
    // 创建一个bench，返回其benchId
    this.leftBench = gum.Scott.create({
      "container": left, "projectId": this.modelGroupId, dock: 4, "system": gum.SystemType.ST_3D
    });
    console.log(this.leftBench);
    // 启动bench，会启动渲染循环
    gum.Scott.run(this.leftBench);
    const tapi: gum.IApi3D = gum.Apis.getApi(this.leftBench)['3D'];
    ///////////////// 注册监听构件选中事件///////////////
    tapi.addSelectEventListener('click', async (result) => {
      if (result.uuids.length == 0) {
        return;
      }
      let uuid = gum.btoa(result.uuids[0]);
      console.log(uuid);

      const res = await this.baseSer.getPropertyById(this.modelGroupId, encodeURIComponent(uuid));
      this.panels[0].detail = [];
      if (this.isJson(res.item)) {
        let Properties = JSON.parse(res.item).PropertySets[0].Properties;
        Properties.forEach((element) => {
          this.panels[0].detail.push({
            name: element.Name,
            value: element.Value
          });
        });
      }
    });
    // let clickFlag = true;
    ///////////////// 工具栏-视点功能点击///////////////
    // tapi.addControlEventListener('printClick', async () => {
    //   console.log('Print Click');
    //   this.clickFlag = !this.clickFlag;
    //   if (this.clickFlag) {
    //     this.leftPanelShow = false;
    //     this.rightPanelShow = false;
    //     this.getViewLists();
    //   }
    // });
    // this.markButton = new MarkPlugin();
    ///////////////// 工具栏-锚点功能点击///////////////
    // tapi.addControlEventListener('markClick', async () => {
    //   console.log('Mark Click Status is: ' + this.clickMark);
    //   this.clickMark = !this.clickMark;
    //   this.markButton.isActive = !this.markButton.isActive;
    //   console.log(this.markButton.isActive);
    //   tapi.enableMarkerDevice(this.markButton.isActive);
    // });

    ///////////////// 工具栏-锚点功能点击///////////////
    // tapi.addWanderEventListener("enable", async () => {
    //   console.log('clickWander Click');
    //   // this.clickMark = !this.clickMark;
    //   this.clickWander = true;
    //   // tapi.enableMarkerDevice(this.clickMark);
    // });

  }



  public getGuid() {
    // div.innerHTML = "<div style='width: 100px;height:50px;background-color:lime;'></div>"
    let s = [];
    let hexDigits = "0123456789abcdef";
    for (let i = 0; i < 36; i++) {
      s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";
    let uuid = s.join("");
    return uuid;
  }

  // 查询相机标签
  public viewLists: any = [];
  public async getViewLists() {
    let res = await this.dataManagementService.queryView(this.modelGroupId);
    this.viewLists = res.items;
    console.log(res.items)
  }

  /**
   * bench增加模型
   * @param model 
   */
  public async addModel(model: AttachmentViewModel) {
    console.log('加载模型：' + model.fileName);
    const tapi = gum.Apis.getApi(this.leftBench);

    let modelPath = CDNFILEURL + '/' + model.filePath;
    console.log(modelPath);
    gum.Scott.load(this.leftBench, {
      url: modelPath,
      workerUrl: "../../../assets/js/",
      orgModelId: model.orgModelId, newModelId: model.newModelId, modelMatrix: model.matrix
    });
    //////////////// 注册模型加载监听事件////////////////
    tapi['3D'].addFileLoaderEventListener(modelPath, 'geomloadend', (result) => {
      let co = Number((result.current / result.totial * 100).toFixed(0));
      model.percent = co;
    });
    this.selectNewModelId.push(model.newModelId);
    this.getModelTreeNode(model);
  }

  /**
   * bench移除模型
   * @param model 
   */
  public removeModel(model: AttachmentViewModel) {
    console.log('卸载模型：' + model.fileName);
    this.selectNewModelId.splice(this.selectNewModelId.indexOf(model.newModelId), 1);
    gum.Scott.remove(this.leftBench, model.newModelId);
    this.showSelectNodeView()
  }

  /**
   * 显示模型目录树选中层级的构件
   */
  showSelectNodeView() {
    const tapi: gum.IApi3D = gum.Apis.getApi(this.leftBench)['3D'];
    const treeList = [];
    const modelTreeList = this.modelTreeList;
    this.getTreeList(modelTreeList, treeList);
    const InstanceGuids = this._neonSrv.SelectFloorAndMajorAndClass(treeList);
    tapi.hiddenAll();
    tapi.setRenderState(InstanceGuids, gum.RenderState.VISIBLE);
    tapi.update();
  }

  public getTreeList(modelTreeList, treeList) {
    modelTreeList.forEach((model) => {
      if (model.treeNode) {
        treeList.push(model.treeNode);
      }
      if (model.children.length > 0) {
        this.getTreeList(model.children, treeList);
      }
    });
  }

  /**
   * 目录树选中渲染模型
   */
  // renderByTreeList() {
  //   const tapi = gum.Apis.getApi(this.leftBench);
  //   let treeList = []
  //   this.modelList.forEach(ele => {
  //     if (ele.visible) {
  //       // let rootNode: NzTreeNodeOptions = { title: ele.fileName, key: ele.orgModelId.toString(), children: ele.treeNode }
  //       // treeList.push(new NzTreeNode(rootNode))
  //       treeList.push(ele.treeNode)
  //     }

  //   });
  //   let InstanceGuids = this._neonSrv.SelectFloorAndMajorAndClass(treeList);
  //   tapi["3D"].hiddenAll();
  //   tapi["3D"].setRenderState(InstanceGuids, gum.RenderState.VISIBLE);
  //   tapi["3D"].update();
  // }

  /**
   * NeonTreeNode转换成NzTreenNode
   */
  private CreateNzTreeNodeFrommGGServiceByAttri = (() => {
    function CreateNodes(NeonTreeNode: NeonTreeNode, NzTreeNode: NzTreeNodeOptions) {
      let count = 0;
      NeonTreeNode.children.map((node) => {
        let InstanceGuids = node.InstanceGuids ? node.InstanceGuids : [];
        let option: NzTreeNodeOptions = { title: node.title, checked: true, InstanceGuids, key: NzTreeNode.key + '-' + count++, children: [] };
        NzTreeNode.children.push(option);
        CreateNodes(node, option);
      });

      if (NeonTreeNode.children.length === 0) {
        NzTreeNode.isLeaf = true;
      }
    }
    return (NeonTree: NeonTreeNode) => {
      let count = 0;
      let rootNode: NzTreeNodeOptions = { title: NeonTree.title, key: String(count++), children: [] };
      CreateNodes(NeonTree, rootNode);
      return new NzTreeNode(rootNode);
    };
  })();

  /**
   * NeonTreeNode转换成NzTreenNode
   */
  public async getModelTreeNode(model: AttachmentViewModel): Promise<void> {
    model.loading = true;
    let respose = await this.getModelTreeSev(model.modelGroupId, model.newModelId);
    let NzTree;
    if (this.isJson(respose.item)) {
      let NeonTree = this._neonSrv.GetTreeFilterFromAttri(JSON.parse(respose.item), model.fileName);
      NzTree = this.CreateNzTreeNodeFrommGGServiceByAttri(NeonTree);
    }
    // let rootNode: NzTreeNodeOptions = { title: model.fileName, key: model.orgModelId, children: NzTree }
    model.treeNode = NzTree;
    model.loading = false;
  }

  /**
   * 通用方法
   * @param json 
   */
  public isJson(json) {
    try {
      let obj = JSON.parse(json);
      if (typeof obj == 'object' && obj) {
        return true;
      } else {
        return false;
      }
    } catch (e) {
      return false;
    }
  }

  /**
   * 遍历目录树查找newModelId
   * @param modelTreeList 
   * @param newModelId 
   */
  // public loopFindModelByNewModelId(modelTreeList, newModelId: number) {
  //   for (let i = 0; i < modelTreeList.length; i++) {
  //     const model = modelTreeList[i];
  //     if (model.newModelId == newModelId) {
  //       return model;
  //     }
  //     if (model.children.length > 0) {
  //       this.loopFindModelByNewModelId(model.children, newModelId);
  //     }
  //   }
  // }
  public THFindMatchValue = (() => {
    let resultArr = new Array();
    let getTickMenuId = function (obj, key, val) {
      if (undefined == obj || null == obj || !(obj instanceof Object)) {
        return;
      }
      if (obj[key] && obj[key] == val) {
        resultArr.push(obj);
      }
      if (null != obj.children && obj.children instanceof Array) {
        for (let child of obj.children) {
          getTickMenuId(child, key, val);
        }
      }
    };
    return (arr, key?: string, val?) => {
      resultArr = new Array();
      if (arr.length > 0) {
        for (let rootMenu of arr) {
          getTickMenuId(rootMenu, key, val);
        }
      }
      return resultArr;
    };
  })();


}

